home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
651-660
/
658
/
view
/
dcback
/
dcback.c
next >
Wrap
C/C++ Source or Header
|
1995-03-15
|
14KB
|
428 lines
/*-- AutoRev header do NOT edit!
*
* Program : dcback.c
* Copyright : © 1991 Jaba Development
* Author : Jan van den Baard
* Creation Date : 16-Nov-91
* Current version : 1.2
* Translator : DICE v2.6.
*
* REVISION HISTORY
*
* Date Version Comment
* --------- ------- ------------------------------------------
* 29-Feb-92 1.2 Now uses "SetArgStr()".
* 23-Nov-91 1.1 Command line promting now allowed.
* 16-Nov-91 1.0 Auto detach 2.0 argument parsing startup.
*
*-- REV_END --*/
#include <exec/types.h>
#include <exec/memory.h>
#include <exec/execbase.h>
#include <exec/libraries.h>
#include <exec/alerts.h>
#include <dos/dos.h>
#include <dos/dosextens.h>
#include <dos/rdargs.h>
#include <workbench/startup.h>
#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <lib/misc.h>
/*
* --- These globals MUST be defined somewhere in your source!
*/
extern UBYTE *_procname; /* process name */
extern UBYTE *_template; /* commandline template */
extern UBYTE *_exthelp; /* extended command line help */
extern LONG _stack; /* process stack */
extern LONG _priority; /* process priority */
extern LONG _BackGroundIO; /* open background io channel */
/*
* --- externally referenced structures.
*/
extern struct ExecBase *SysBase; /* to check for V36 minimum */
extern struct WBStartup *_WBMsg; /* guess what.... */
/*
* --- This is how both main() and wbmain() are called.
*/
extern long main( long, long * );
extern long wbmain( struct WBStartup * );
/*
* --- Proto for the exit routine
*/
long exit( long );
/*
* --- Data that isn't chucked in the BSS section.
*/
BPTR _DetachDir = 0l; /* process current dir */
BPTR _Backstdout = 0l; /* io channel */
UBYTE _IsDetached = FALSE; /* detached flag */
ULONG *_DosArray = 0l; /* commandline array */
UWORD _NumArgs = 0l; /* max # of args */
UBYTE *_Arguments = 0l; /* argument line */
struct RDArgs *_DosSource = 0l; /* for the arguments */
/*
* --- New _main() which checks if it is run from the shell or
* --- the workbench.
*/
__stkargs long _main( long len, char *lin )
{
struct Process *ThisTask;
struct CommandLineInterface *cli;
struct MemList *mlist;
BPTR *SegList, *TmpSeg, StdOut;
ULONG SegCount = 0l, ArgCount = 0l;
BYTE DetachRun = FALSE;
UBYTE *Tmp;
ULONG alert;
/*
* --- First we must see wether we are running
* --- under 2.0 or not. We need 2.0 for the
* --- commandline parsing!
*/
if ((( struct Library *)SysBase)->lib_Version < 36 )
return( RETURN_FAIL );
/*
* --- Get a pointer to our Task (Process)
*/
ThisTask = ( struct Process * )SysBase->ThisTask;
/*
* --- When run from the shell the process has
* --- a CLI structure. If this is the case
* --- the 'DetachRun' flag is set to TRUE so we
* --- we know that the program still has to be
* --- detached.
*/
if ( ThisTask->pr_CLI )
DetachRun = TRUE;
/*
* --- When either the 'DetachRun' or '_IsDetached' flag
* --- is TRUE it means that we are run from the shell.
*/
if ( DetachRun || _IsDetached ) {
/*
* --- Check if we are detached yet...
*/
if ( ! _IsDetached ) {
/*
* --- We arn't detached yet so we must parse
* --- the arguments given to us by the shell.
*/
if ( Tmp = _template ) {
/*
* --- There is a template string supplied
*/
if ( *Tmp ) {
/*
* --- The template string even got characters in it!
* --- Now we must count the maximum number of arguments
* --- we can expect. This is done by counting the
* --- commas in the template string and then adding
* --- one to the result
*/
while ( *Tmp ) {
if ( *Tmp == ',' ) ArgCount++;
Tmp++;
}
ArgCount++;
}
}
/*
* --- Allocate and parse the arguments.
*/
if ( ArgCount ) {
/*
* --- There are arguments to be expected.
*/
_NumArgs = ArgCount; /* save argument count */
_Arguments = lin; /* save the argument line pointer */
/*
* --- Allocate our RDArgs structure.
*/
if ( ! ( _DosSource = ( struct RDArgs * )AllocVec((long)sizeof( struct RDArgs ), MEMF_PUBLIC | MEMF_CLEAR ))) {
alert = AT_Recovery | AG_NoMemory | AO_Unknown;
goto suError;
}
/*
* --- Setup the RDArgs structure for extended help.
*/
_DosSource->RDA_ExtHelp = _exthelp;
/*
* --- Try to allocate the array that will hold
* --- the result of the parse.
*/
if ( ! (_DosArray = (ULONG *)AllocVec( ArgCount * sizeof( LONG ), MEMF_PUBLIC | MEMF_CLEAR ))) {
alert = AT_Recovery | AG_NoMemory | AO_Unknown;
goto suError;
}
/*
* --- Try to parse the arguments from STDIN.
*/
if ( ! ReadArgs( _template, _DosArray, _DosSource )) {
if ( StdOut = Output())
Write( StdOut, "Bad Args\n", 9l );
alert = 0l;
goto suError;
}
}
}
/*
* --- This code only get's executed when the program
* --- was started from the shell and isn't detached yet.
*/
if ( cli = ( struct CommandLineInterface * )BADDR( ThisTask->pr_CLI )) {
/*
* --- Get a copy of the lock to the current directory
*/
CurrentDir( _DetachDir = CurrentDir( 0l ));
_DetachDir = DupLock( _DetachDir );
/*
* --- Mark us as detached ( a little premature but so what.. )
*/
_IsDetached = TRUE;
/*
* --- Open a io channel if requested
*/
if ( _BackGroundIO )
_Backstdout = Open( "*", MODE_OLDFILE );
/*
* --- Sanity check. If the stack is 0 then make the stack 4096
*/
if ( ! _stack )
_stack = 4096l;
/*
* --- Try to launch us as a non-cli process
*/
if ( CreateProc( _procname, _priority, cli->cli_Module, _stack )) {
/*
* --- Don't rip the code out from under us
*/
cli->cli_Module = 0l;
/*
* --- We must make sure that dos doesn't deallocate
* --- our arguments before we get a chance to use
* --- them.
*/
SetArgStr( 0l );
return ( RETURN_OK );
} else {
alert = AT_Recovery | AG_ProcCreate | AO_Unknown;
goto suError;
}
} else {
/*
* --- Getting here means that we now run as a non-cli
* --- process initially started from a shell.
*/
if ( ! strcmp( ThisTask->pr_Task.tc_Node.ln_Name, _procname )) {
/*
* --- Now we are running detached we must make sure that
* --- dos deallocates the commandline (if there) when
* --- we exit.
*/
SetArgStr( _Arguments );
/*
* --- Now we must make sure that we get deallocated
* --- when the program exits. This is done by creating
* --- a MemList with pointers to all our segments in
* --- it and then AddTail'ing this to the Task it's
* --- MemList which automatically get's deallocated
* --- by the system.
*/
SegList = ( BPTR * )BADDR( ThisTask->pr_SegList );
SegList = ( BPTR * )BADDR( SegList[3] );
TmpSeg = SegList;
/*
* --- Count the number of segments we have.
*/
while ( SegList ) {
SegList = ( BPTR * )BADDR( *SegList );
SegCount++;
}
/*
* --- Try to allocate a MemList with enough MemEntry's
* --- I didn't use AllocVec because the system deallocates
* --- this structure itself with FreeMem() and not FreeVec()
* --- (I think........)
*/
if ( mlist = ( struct MemList * )AllocMem( sizeof( struct MemList ) + sizeof( struct MemEntry ) * ( SegCount - 1 ), MEMF_PUBLIC | MEMF_CLEAR )) {
SegList = TmpSeg;
mlist->ml_NumEntries = SegCount;
SegCount = 0l;
/*
* --- Initialize all MemEntries
*/
while ( SegList ) {
mlist->ml_me[ SegCount ].me_Addr = (APTR)&SegList[ -1 ];
mlist->ml_me[ SegCount ].me_Length = SegList[ -1 ];
SegList = ( BPTR * )BADDR( *SegList );
SegCount++;
}
/*
* --- Add our MemList to the Task it's MemList.
*/
AddTail( &ThisTask->pr_Task.tc_MemEntry, &mlist->ml_Node );
/*
* --- Set our current dir
*/
CurrentDir( _DetachDir );
/*
* --- If an io channel was requested we must
* --- initialize the proper stdio structures
*/
if ( _BackGroundIO ) {
ThisTask->pr_COS = _Backstdout;
_IoStaticFD[1].fd_Fh = _Backstdout;
_IoStaticFD[1].fd_Flags = O_RDWR | O_NOCLOSE | O_ISOPEN;
_IoStaticFD[2].fd_Fh = _Backstdout;
_IoStaticFD[2].fd_Flags = O_RDWR | O_NOCLOSE | O_ISOPEN;
_finitdesc( stdout, 1, __SIF_WRITE | __SIF_NOFREE );
_finitdesc( stderr, 2, __SIF_WRITE | __SIF_NOFREE );
}
/*
* --- Now we just exit with whatever main()
* --- returns to us.
*/
exit( main( (long)_NumArgs, _DosArray ));
} else {
alert = AT_Recovery | AG_NoMemory | AO_Unknown;
goto suError;
}
}
}
} else {
/*
* --- Getting here means we have been started from the workbench.
*/
if ( _WBMsg->sm_ArgList )
/*
* --- CurrentDir to the directory we are started from
*/
CurrentDir( _WBMsg->sm_ArgList->wa_Lock );
/*
* --- Now we just exit with whatever wbmain()
* --- returns to us.
*/
exit( wbmain( _WBMsg ));
}
/*
* --- This is never called! It just brings in the code that
* --- waits for the Workbench message for when we are started
* --- from the workbench! See wbmain.a!
*/
_waitwbmsg();
/*
* --- Here's where we land when something failed.
* --- This cleans up the mess we made except when we
* --- got here because the MemList could not be
* --- allocated! If that's the case the segments wont
* --- be deallocated. This shouldn't be a problem
* --- because when the MemList cannot be allocated anymore
* --- your system is really fuc#@$$##@ up!
*/
suError:
if ( _DosSource ) {
FreeArgs( _DosSource );
FreeVec( _DosSource );
}
if ( _DosArray ) FreeVec( _DosArray );
if ( _DetachDir ) UnLock( _DetachDir );
if ( alert ) Alert( alert );
return( RETURN_FAIL );
}
#include <lib/atexit.h>
typedef struct Process Process;
AtExit *_ExitBase;
/*
* --- A New exit which cleans up the mess we made.
*/
long exit( long code )
{
AtExit *eb;
/*
* --- If opened, close the io channel
*/
if ( _Backstdout )
Close( _Backstdout );
/*
* --- UnLock our current dir
*/
if ( _DetachDir )
UnLock( _DetachDir );
/*
* --- Deallocate our argument array
*/
if ( _DosArray )
FreeVec( _DosArray );
/*
* --- Cleanup our RDArgs structure
*/
if ( _DosSource ) {
FreeArgs( _DosSource );
FreeVec( _DosSource );
}
/*
* --- Ask Matthew...... I don't know!
*/
for (eb = _ExitBase; eb; eb = eb->Next)
(*eb->Func)();
/*
* --- Low level exit
*/
_exit(code);
}